<?php

/**
 * Contains the errorHandler function to log site errors.
 *
 * PHP Version 5
 *
 * @category BuyLocal
 * @package  BuyLocal
 * @author   Kevin Fodness <kevin.fodness@gmail.com>
 * @author   Mike Pennisi <mpennisi@andrew.cmu.edu>
 * @author   Aaron Ryden <aryden@gmail.com>
 * @author   Spencer Hakim <hakims@rpi.edu>
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
 * @link     http://code.google.com/p/buylocalopensourcerensselaer/
 */

/** @uses printError For user-friendly display of errors. */
require_once 'function_printerror.php';

/** @uses valueOf For safe handling of arrays. */
require_once 'function_valueof.php';
 
/**
 * Error handler function for logging site errors.
 *
 * This function is structured to enforce strict compliance to PEAR standards:
 * any error, warning, or notice will cause the script execution to halt after
 * the error has been logged.
 *
 * @param int    $errno      Contains the level of the error raised. 
 * @param string $errstr     Contains the error message.
 * @param string $errfile    Contains the filename that the error was raised in.
 * @param int    $errline    Contains the line number the error was raised at.
 * @param array  $errcontext The active symbol table at error trigger time.
 *
 * @access public
 * @return null
 */
function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
{
    /**
     * Prints non-descriptive user-targeted message.
     *
     * The lack of specificity in this message prevents exploitation of the
     * codebase by gaining information about the code based on the content of
     * error messages.
     */
    printError('An internal error occurred.');
    
    /** Logs the error to the error log file. */
    switch ($errno) {
    case E_NOTICE:
    case E_USER_NOTICE:
        $errtype = 'Notice';
        break;
    case E_WARNING:
    case E_USER_WARNING:
        $errtype = 'Warning';
        break;
    case E_ERROR:
    case E_USER_ERROR:
        $errtype = 'Fatal Error';
        break;
    default:
        $errtype = 'Unknown';
        break;
    }
    
    $stacktrace = "Stacktrace:\n";
    $stack      = debug_backtrace();
    
    /**
     * 'function' is offset by +1 to show called function in its proper file,
     * not the file it was called from.
     */
    for ($i = 0; $i < count($stack); $i++) {
        /**
         * Custom output for the last call in the stack, which is always
         * the "main" function (referred to as __MAIN__ in the output).
         */
        if ($i + 1 < count($stack)) {
            /** Format args. */
            $arguments = valueOf(valueOf($stack, $i+1), 'args');
            if (!is_array($arguments)) {
                continue;
            }
            foreach ($arguments as &$arg) {
                if (is_string($arg)) {
                    if (strlen($arg) > 40) {
                        $arg = substr($arg, 0, 40) . '[...]';
                    }
                    $arg = "'" . $arg . "'";
                    
                } else if (is_object($arg)) {
                    $arg = '[' . get_class($arg) . ' Object]';
                    
                } else if (is_bool($arg)) {
                    $arg = $arg === true ? 'true' : 'false';
                    
                } else if (is_array($arg)) {
                    /**
                     * Only handles first level of array.
                     * If you want more than that, just call print_r on
                     * debug_backtrace(), it'll print everything, ever.
                     */
                    $arg = 'Array(' . implode(', ', $arg) . ')';
                }
            }
            
            $stacktrace .= "\t`" . valueOf(valueOf($stack, $i+1), 'class')
                . valueOf(valueOf($stack, $i+1), 'type')
                . valueOf(valueOf($stack, $i+1), 'function') . '(' 
                . implode(', ', valueOf(valueOf($stack, $i+1), 'args'))
                . ')` at line '
                . valueOf(valueOf($stack, $i), 'line') . ' in `'
                . valueOf(valueOf($stack, $i), 'file') . "`\n";
            
        } else {
            $stacktrace .= "\t" . '`__MAIN__` at line '
                . valueOf(valueOf($stack, $i), 'line')
                . ' in `' . valueOf(valueOf($stack, $i), 'file') . "`\n";
        }
    }
    
    $message = date('Y/m/d H:i:s') . ' `' .$errfile . ':' . $errline . '` - '
        . $errtype . ': ' . $errstr . "\n" . $stacktrace . "\n";
    error_log($message, 3, ERRORLOG);
    exit(1);
}

?>